import Select, { SelectEvent } from 'ol/interaction/Select'
import { noModifierKeys } from 'ol/events/condition'
import GeoJSON from 'ol/format/GeoJSON'
import Feature from 'ol/Feature'
import Point from 'ol/geom/Point'
import DragBox from 'ol/interaction/DragBox'
import Circle from 'ol/geom/Circle'
import * as turf from '@turf/turf'
import MultiLineString from 'ol/geom/MultiLineString'
import ModifyFeature from 'ol-ext/interaction/ModifyFeature'
import VectorSource from 'ol/source/Vector'
import { transform } from 'ol/proj'

function clearSelect(vue) {
  vue.selectInteraction.dispatchEvent(
    new SelectEvent('select', [], vue.selectInteraction.getFeatures(), null)
  )
  vue.selectInteraction.getFeatures().clear()
  if (vue.map.tmpDragBox) {
    vue.map.removeInteraction(vue.map.tmpDragBox)
    vue.map.tmpDragBox = null
    vue.isSelectInteractionActive = false
  }
}

export function fireOperate(type, vue, param) {
  const map = vue.map

  switch (type) {
    case 'Select': {
      if (map.tmpDragBox) {
        // go to disable
        clearSelect(vue)
        map.removeInteraction(map.tmpDragBox)
        map.tmpDragBox = null
        vue.isSelectInteractionActive = false
      } else {
        vue.isSelectInteractionActive = true
        const selectedFeatures = vue.selectInteraction.getFeatures()
        const dragBox = new DragBox({
          condition: noModifierKeys,
        })
        dragBox.on('boxend', function () {
          const direction =
            dragBox.box_.startPixel_[0] <= dragBox.box_.endPixel_[0] &&
            dragBox.box_.startPixel_[1] <= dragBox.box_.endPixel_[1]
              ? 'l2r'
              : 'r2l'
          const layerSources = [
            vue.qtLayer.getSource(),
            vue.pmLayer.getSource(),
            vue.kwLayer.getSource(),
            vue.tzjLayer.getSource(),
            vue.dlLayer.getSource(),
            vue.gdkLayer.getSource(),
            vue.assistLayer.getSource(),
          ]
          layerSources.forEach((s) =>
            s.forEachFeature(function (feature) {
              if (direction === 'r2l') {
                const extent = new GeoJSON().writeGeometryObject(
                  dragBox
                    .getGeometry()
                    .clone()
                    .transform('EPSG:3857', 'EPSG:4326')
                )
                const geom = feature
                  .getGeometry()
                  .clone()
                  .transform('EPSG:3857', 'EPSG:4326')
                let geomJson = null
                if (geom instanceof Circle)
                  geomJson = new GeoJSON().writeGeometryObject(
                    new Point(geom.getCenter())
                  )
                else if (geom instanceof MultiLineString) {
                  const ext = geom.getExtent()
                  geomJson = turf.polygon([
                    [
                      [ext[0], ext[1]],
                      [ext[0], ext[3]],
                      [ext[2], ext[3]],
                      [ext[2], ext[1]],
                      [ext[0], ext[1]],
                    ],
                  ])
                } else geomJson = new GeoJSON().writeGeometryObject(geom)
                if (turf.booleanContains(extent, geomJson))
                  selectedFeatures.push(feature)
              } else if (direction === 'l2r' && feature.getGeometry().intersectsExtent(dragBox.getGeometry().getExtent())) selectedFeatures.push(feature)
            })
          )
          vue.selectInteraction.dispatchEvent(
            new SelectEvent('select', selectedFeatures, [], null)
          )
        })
        dragBox.on('boxstart', function () {
          vue.selectInteraction.dispatchEvent(
            new SelectEvent(
              'select',
              [],
              vue.selectInteraction.getFeatures(),
              null
            )
          )
          vue.selectInteraction.getFeatures().clear()
        })
        clearSelect(vue)
        map.addInteraction(dragBox)
        map.tmpDragBox = dragBox
      }
      break
    }
    case 'Delete': {
      if (!vue.selectInteraction.getActive()) return
      const features = vue.selectInteraction.getFeatures()
      if (!features.getLength()) vue.mapNotification.show('请选择具体元素')
      else {
        for (let i = 0, f; (f = features.item(i)); i++) {
          const fType = f.getId().split('-')[0]
          if (fType.endsWith('QT')) {
            vue.qtLayer.getSource().removeFeature(f)
          } else if (fType.endsWith('GDK')) {
            vue.gdkLayer.getSource().removeFeature(f)
          } else if (fType === 'PM') {
            vue.dlLayer
              .getSource()
              .getFeatures()
              .filter(
                (dl) =>
                  dl.get('dbid') !== undefined &&
                  f
                    .getGeometry()
                    .intersectsCoordinate(dl.getGeometry().getCoordinates())
              )
              .map((dl) => vue.dlLayer.getSource().removeFeature(dl))
            vue.pmLayer.getSource().removeFeature(f)
          } else if (fType.endsWith('GK')) {
            vue.kwLayer.getSource().removeFeature(f)
          } else if (fType === 'TZJ') {
            vue.tzjLayer.getSource().removeFeature(f)
          } else if (fType === 'ZHUJI' || fType === 'JLX') {
            vue.assistLayer
              .getSource()
              .getFeatures()
              .map((ff) => {
                if (ff.getId() === f.getId()) return ff
              })
              .forEach((ff) => {
                if (ff !== undefined)
                  vue.assistLayer.getSource().removeFeature(ff)
              })
          } else {
            vue.dlLayer.getSource().removeFeature(f)
          }
        }
        vue.mapNotification.show(features.getLength() + ' 个元素已删除')
        vue.selectInteraction.getFeatures().clear()
      }
      break
    }
    case 'Transform': {
      const features = vue.selectInteraction.getFeatures()
      if (!features.getLength()) {
        if (!vue.transformInteraction.getActive())
          vue.mapNotification.show('请选择具体元素')
        vue.transformInteraction.setActive(false)
      } else {
        vue.transformInteraction.setActive(
          !vue.transformInteraction.getActive()
        )
        const transformFeatures = features.getArray().map((f) => {
          if (f.getId().startsWith('ZHUJI-'))
            return vue.assistLayer
              .getSource()
              .getFeatures()
              .filter((f1) => f1.getId() === f.getId())[0]
          else return f
        })
        transformFeatures.forEach((f) =>
          vue.transformInteraction.select(f, true)
        )
        clearSelect(vue)
      }
      break
    }
    case 'Rotate': {
      const features = vue.selectInteraction.getFeatures()
      if (!features.getLength()) {
        if (!vue.rotateInteraction.getActive())
          vue.mapNotification.show('请选择具体元素')
        vue.rotateInteraction.setActive(false)
      } else {
        vue.rotateInteraction.setActive(!vue.rotateInteraction.getActive())
        const rotateFeatures = features.getArray().map((f) => {
          if (f.getId().startsWith('ZHUJI-'))
            return vue.assistLayer
              .getSource()
              .getFeatures()
              .filter((f1) => f1.getId() === f.getId())[0]
          else return f
        })
        rotateFeatures.forEach((f) => vue.rotateInteraction.select(f, true))
        clearSelect(vue)
      }
      break
    }
    case 'Modify': {
      let features = vue.selectInteraction.getFeatures()
      features.array_ = features.array_.filter((f) => {
        const fType = f.getId().split('-')[0]
        return fType === 'ZHUJI' || fType === 'polyQT'
      })
      features.set('length', features.array_.length)
      if (features.getLength() !== 1) {
        if (!vue.modifyInteraction.getActive())
          vue.mapNotification.show('请选择单个注记/多边形腔体')
        vue.modifyInteraction.setActive(false)
      } else {
        const orig = vue.modifyInteraction.getActive()
        if (orig === false) {
          vue.modifyInteraction = new ModifyFeature({
            source: new VectorSource({ features: features }),
          })
          vue.map.addInteraction(vue.modifyInteraction)
        } else vue.modifyInteraction.setActive(false)
      }
      break
    }
    case 'ChangeName': {
      if (vue.selectInteraction.getFeatures().getLength() === 1) {
        const fType = vue.selectInteraction.getFeatures().getArray()[0].getId()
        if (fType.startsWith('PM-')) {
          vue.pmNamePanelVisble = true
          const name = vue.selectInteraction
            .getFeatures()
            .getArray()[0]
            .get('name')
          vue.pmName_feature = vue.selectInteraction.getFeatures().getArray()[0]
          if (name !== undefined && name !== null) {
            vue.pmName_direction = name[0]
            vue.pmName_seq = name[1]
          } else {
            vue.pmName_direction = '北'
            vue.pmName_seq = '1'
          }
        } else if (fType.startsWith('ZHUJI-')) {
          if (vue.selectInteraction.getFeatures().getArray()[0].get('text')) {
            vue.zhujiPanelVisble = true
            vue.zhuji_feature = vue.selectInteraction
              .getFeatures()
              .getArray()[0]
            vue.zhuji_text = vue.selectInteraction
              .getFeatures()
              .getArray()[0]
              .get('text')
          } else {
            vue.mapNotification.show('该注记内容来自数据库')
          }
        }
      } else {
        vue.mapNotification.show('请选择单个剖面/注记')
      }
      break
    }
    case 'Undo': {
      vue.undoInteraction.undo()
      break
    }
    case 'Redo': {
      vue.undoInteraction.redo()
      break
    }
    case 'Read': {
      const features = new GeoJSON({
        dataProjection: 'EPSG:4326',
        featureProjection: 'EPSG:3857',
      }).readFeatures(param)

      features.forEach((f) => {
        const fType = f.getId().split('-')[0]
        if (fType.endsWith('QT')) {
          if (fType.indexOf('circleQT') >= 0) {
            if (f.getGeometry() instanceof Point) {
              const polyCircle = turf.circle(
                transform(
                  f.getGeometry().getCoordinates(),
                  'EPSG:3857',
                  'EPSG:4326'
                ),
                f.get('size') / 2 / 1000000
              )
              const radius = Math.abs(
                transform(
                  polyCircle.geometry.coordinates[0][0],
                  'EPSG:4326',
                  'EPSG:3857'
                )[1] - f.getGeometry().getCoordinates()[1]
              )
              const circleF = new Feature(
                new Circle(f.getGeometry().getCoordinates(), radius)
              )
              circleF.setId(f.getId())
              Object.keys(f.values_)
                .filter((k) => k !== 'geometry')
                .forEach((k) => (circleF.values_[k] = f.values_[k]))
              vue.qtLayer.getSource().addFeature(circleF)
            }
          } else vue.qtLayer.getSource().addFeature(f)
        } else if (fType.endsWith('GDK')) {
          vue.gdkLayer.getSource().addFeature(f)
        } else if (fType === 'PM') {
          if (f.get('connect')) {
            if (f.get('connect') instanceof String)
              f.set('connect', [f.get('connect')])
          } else {
            f.set('connect', [])
          }
          vue.pmLayer.getSource().addFeature(f)
        } else if (fType.endsWith('GK')) {
          if (fType.indexOf('circle') >= 0) {
            const polyCircle = turf.circle(
              transform(
                f.getGeometry().getCoordinates(),
                'EPSG:3857',
                'EPSG:4326'
              ),
              f.get('size') / 2 / 1000000
            )
            const radius = Math.abs(
              transform(
                polyCircle.geometry.coordinates[0][0],
                'EPSG:4326',
                'EPSG:3857'
              )[1] - f.getGeometry().getCoordinates()[1]
            )
            const circleF = new Feature(
              new Circle(f.getGeometry().getCoordinates(), radius)
            )
            circleF.setId(f.getId())
            Object.keys(f.values_)
              .filter((k) => k !== 'geometry')
              .forEach((k) => (circleF.values_[k] = f.values_[k]))
            vue.kwLayer.getSource().addFeature(circleF)
          } else vue.kwLayer.getSource().addFeature(f)
        } else if (
          fType.startsWith('DL') ||
          fType.endsWith('DL') ||
          fType === 'HLX'
        ) {
          if (f.get('dbid')) {
            if (
              Object.values(vue.dlAllData).filter(
                (dls) =>
                  dls.filter((dl) => dl.id === f.get('dbid')).length !== 0
              ).length !== 0
            )
              vue.dlLayer.getSource().addFeature(f)
          } else vue.dlLayer.getSource().addFeature(f)
        } else if (fType === 'TZJ') {
          vue.tzjLayer.getSource().addFeature(f)
        } else if (fType === 'ZHUJI' || fType === 'JLX') {
          if (fType === 'ZHUJI' && f.get('connectDbid')) {
            if (
              Object.values(vue.dlAllData).filter(
                (dls) =>
                  dls.filter((dl) => dl.id === f.get('connectDbid')).length !==
                  0
              ).length !== 0
            )
              vue.assistLayer.getSource().addFeature(f)
          } else vue.assistLayer.getSource().addFeature(f)
        }
      })
      break
    }
    case 'Save': {
      const features = []

      vue.qtLayer
        .getSource()
        .getFeatures()
        .forEach((f) => {
          if (f.getId().indexOf('circleQT') >= 0) {
            if (f.getGeometry() instanceof Circle) {
              const feature = new Feature(
                new Point(f.getGeometry().getCenter())
              )
              feature.setId(f.getId())
              Object.keys(f.values_)
                .filter((k) => k !== 'geometry')
                .forEach((k) => (feature.values_[k] = f.values_[k]))
              features.push(feature)
            }
          } else features.push(f)
        })
      features.push(...vue.gdkLayer.getSource().getFeatures())
      features.push(...vue.pmLayer.getSource().getFeatures())
      features.push(...vue.tzjLayer.getSource().getFeatures())
      vue.kwLayer
        .getSource()
        .getFeatures()
        .forEach((f) => {
          if (f.getId().indexOf('circle') >= 0) {
            const feature = new Feature(new Point(f.getGeometry().getCenter()))
            feature.setId(f.getId())
            Object.keys(f.values_)
              .filter((k) => k !== 'geometry')
              .forEach((k) => (feature.values_[k] = f.values_[k]))
            features.push(feature)
          } else features.push(f)
        })
      features.push(...vue.dlLayer.getSource().getFeatures())
      features.push(...vue.assistLayer.getSource().getFeatures())
      const paintJson = new GeoJSON({
        dataProjection: 'EPSG:4326',
        featureProjection: 'EPSG:3857',
      }).writeFeatures(features)

      // generate relation
      const pmJson = vue.pmLayer
        .getSource()
        .getFeatures()
        .map((pm) => {
          return {
            pid: pm.getId(),
            connect: pm.get('connect'),
            name: pm.get('name'),
            geom: turf.polygon(pm.getGeometry().getCoordinates()),
            children: [],
          }
        })
      const gkJson = vue.kwLayer
        .getSource()
        .getFeatures()
        .map((gk) => {
          if (gk.getGeometry() instanceof Circle) {
            const extents = gk.getGeometry().getExtent()
            return {
              pid: gk.getId(),
              size: gk.get('size'),
              material: gk.get('material'),
              geom: turf.polygon([
                [
                  [extents[0], extents[1]],
                  [extents[0], extents[3]],
                  [extents[2], extents[3]],
                  [extents[2], extents[1]],
                  [extents[0], extents[1]],
                ],
              ]),
              children: [],
            }
          } else {
            return {
              pid: gk.getId(),
              size: gk.get('size'),
              material: gk.get('material'),
              geom: turf.polygon(gk.getGeometry().getCoordinates()),
              children: [],
            }
          }
        })
      // process dl
      vue.dlLayer
        .getSource()
        .getFeatures()
        .forEach((dl) => {
          let dlj
          if (dl.get('dbid')) dlj = { pid: dl.getId(), dbid: dl.get('dbid') }
          else dlj = { pid: dl.getId(), name: dl.get('name') }
          gkJson.every((gk, _) => {
            if (
              turf.booleanContains(
                turf.toWgs84(gk.geom),
                turf.toWgs84(turf.point(dl.getGeometry().getCoordinates()))
              )
            ) {
              gk.children.push(dlj)
              dlj = null
              return false
            }
            return true
          })
          // not in gk
          if (dlj !== null) {
            pmJson.every((pm, _) => {
              if (
                turf.booleanContains(
                  turf.toWgs84(pm.geom),
                  turf.toWgs84(turf.point(dl.getGeometry().getCoordinates()))
                )
              ) {
                pm.children.push(dlj)
                dlj = null
                return false
              }
              return true
            })
          }
        })
      // process gk
      gkJson.forEach((gk) => {
        pmJson.every((pm, _) => {
          if (
            turf.booleanContains(turf.toWgs84(pm.geom), turf.toWgs84(gk.geom))
          ) {
            delete gk.geom
            pm.children.push(gk)
            return false
          }
          return true
        })
      })
      // process pm
      pmJson.forEach((pm) => delete pm.geom)
      vue.currentWell.wellSectionContent = {
        paint: JSON.parse(paintJson),
        relation: pmJson,
      }

      break
    }
  }
}

// WEBPACK FOOTER //
// ./src/components/pmEditor/operate.js
